package com.acctrue.zentao.utils;

import com.google.gson.JsonParser;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Request.Builder;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang3.ObjectUtils;

import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author: 孙炯炯
 * @since: 2023/8/18
 **/
public class OkHttpUtil {
    private static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
    private static final MediaType XML = MediaType.parse("application/xml;charset=utf-8");
    private static final MediaType FORM_DATA = MediaType.parse("multipart/form-data");

    private final static OkHttpClient CLIENT = new OkHttpClient.Builder()
            .callTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .connectTimeout(30, TimeUnit.SECONDS)
            .build();

    public static ResponseResult<String> doGet(String url) {
        return doGet(url, (Map) null, (Map) null);
    }

    public static ResponseResult<String> doGet(String url, Map<String, String> params) {
        return doGet(url, params, (Map) null);
    }

    public static ResponseResult<String> doGet(String url, Map<String, String> params, Map<String, String> headerMap) {
        StringBuilder sb = new StringBuilder(url);
        if (params != null && !params.isEmpty()) {
            boolean firstFlag = true;
            Iterator var6 = params.entrySet().iterator();

            while (var6.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry) var6.next();
                if (firstFlag) {
                    sb.append('?').append(entry.getKey()).append('=').append(entry.getValue());
                    firstFlag = false;
                } else {
                    sb.append('&').append(entry.getKey()).append('=').append(entry.getValue());
                }
            }
        }

        Builder builder = new Builder();
        if (headerMap != null && !headerMap.isEmpty()) {
            Objects.requireNonNull(builder);
            headerMap.forEach(builder::addHeader);
        }
        Request request = builder.url(sb.toString()).build();
        return execute(request);
    }

    public static ResponseResult<String> doPost(String url, Map<String, String> params) {
        return doPost(url, params, (Map) null);
    }

    public static ResponseResult<String> doPost(String url, Map<String, String> params, Map<String, String> headerMap) {
        okhttp3.FormBody.Builder formBuilder = new okhttp3.FormBody.Builder();
        if (params != null && !params.isEmpty()) {
            Objects.requireNonNull(formBuilder);
            params.forEach(formBuilder::add);
        }

        Builder requestBuilder = new Builder();
        if (headerMap != null && !headerMap.isEmpty()) {
            Objects.requireNonNull(requestBuilder);
            headerMap.forEach(requestBuilder::addHeader);
        }

        Request request = requestBuilder.url(url).post(formBuilder.build()).build();
        return execute(request);
    }

    public static ResponseResult<String> doFormData(String url, Map<String, Object> params, Map<String, String> headerMap) {
        okhttp3.MultipartBody.Builder formBuilder = new okhttp3.MultipartBody.Builder();
        formBuilder.setType(FORM_DATA);
        if (params != null && !params.isEmpty()) {
            Iterator var5 = params.entrySet().iterator();

            while (var5.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry) var5.next();
                Object object = entry.getValue();
                if (object instanceof File) {
                    File file = (File) object;
                    formBuilder.addFormDataPart(entry.getKey(), file.getName(), RequestBody.create(FORM_DATA, file));
                } else if (object instanceof byte[]) {
                    byte[] b = (byte[]) object;
                    Object fileName = params.get("fileName");
                    formBuilder.addFormDataPart(entry.getKey(), ObjectUtils.isNotEmpty(fileName) ? String.valueOf(fileName) : "", RequestBody.create(FORM_DATA, b));
                } else {
                    formBuilder.addFormDataPart(entry.getKey(), object.toString());
                }
            }
        }

        Builder requestBuilder = new Builder();
        if (headerMap != null && !headerMap.isEmpty()) {
            Objects.requireNonNull(requestBuilder);
            headerMap.forEach(requestBuilder::addHeader);
        }

        Request request = requestBuilder.url(url).post(formBuilder.build()).build();
        return execute(request);
    }

    public static ResponseResult<String> doPostJson(String url, String json, Map<String, String> headerMap) {
        return executePost(url, json, JSON, headerMap);
    }

    public static ResponseResult<String> doPostXml(String url, String xml, Map<String, String> headerMap) {
        return executePost(url, xml, XML, headerMap);
    }

    public static String buildCookie(Map<String, Object> params) {
        StringBuilder sb = new StringBuilder();
        for (String key : params.keySet()) {
            sb.append(key).append("=").append(params.get(key)).append(";");
        }
        return sb.toString();
    }

    private static ResponseResult<String> executePost(String url, String data, MediaType contentType, Map<String, String> headerMap) {
        RequestBody requestBody = RequestBody.create(contentType, data);
        Builder requestBuilder = new Builder();
        if (headerMap != null && !headerMap.isEmpty()) {
            Objects.requireNonNull(requestBuilder);
            headerMap.forEach(requestBuilder::addHeader);
        }

        Request request = requestBuilder.url(url).post(requestBody).build();
        return execute(request);
    }

    private static ResponseResult<String> execute(Request request) {
        ResponseResult result;
        Response response = null;
        try {
            response = CLIENT.newCall(request).execute();
            if (!response.isSuccessful()) {
                result = ResponseResult.error(String.valueOf(response.code()), response.message());
                return result;
            }
            String bodyData = response.body().string();
            result = ResponseResult.success(bodyData);
            // 校验返回的数据是否是json
            JsonParser.parseString(bodyData);
            return result;
        } catch (Exception ex) {
            result = ResponseResult.errorMessage(ex.getMessage());
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (Throwable ex) {

                }
            }
        }
        return result;
    }
}
